import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib.pylab import date2num
import mplfinance as mpf
import matplotlib.dates as mdates

# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号

class BYDStockAnalyzer:
    """
    比亚迪股票数据分析类
    用于分析比亚迪股票价格走势并进行可视化
    """
    
    def __init__(self, file_path):
        """
        初始化分析器
        
        Args:
            file_path: Excel文件路径
        """
        self.file_path = file_path
        self.data = None
    
    def load_data(self):
        """
        加载Excel数据
        """
        print("正在读取数据...")
        self.data = pd.read_excel(self.file_path)
        print(f"数据读取完成，数据形状: {self.data.shape}")
        return self.data
    
    def display_data_info(self):
        """
        显示数据基本信息和前5行数据
        """
        print("\n数据前5行:")
        print(self.data.head())
        
        print("\n数据信息:")
        print(self.data.info())
        
        print("\n数据描述性统计:")
        # 选择数值型列进行描述性分析
        numeric_cols = self.data.select_dtypes(include=['float64', 'int64']).columns
        print(self.data[numeric_cols].describe())
    
    def calculate_correlation(self):
        """
        计算相关系数并绘制热力图
        """
        print("\n计算相关系数...")
        # 选择数值型列计算相关系数
        numeric_cols = self.data.select_dtypes(include=['float64', 'int64']).columns
        corr_matrix = self.data[numeric_cols].corr()
        
        print("相关系数矩阵:")
        print(corr_matrix)
        
        # 绘制热力图
        plt.figure(figsize=(10, 8))
        sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', fmt='.2f', linewidths=0.5)
        plt.title('比亚迪股票各指标相关系数热力图')
        plt.tight_layout()
        plt.savefig('correlation_heatmap.png', dpi=300)
        plt.close()
        print("相关系数热力图已保存为 'correlation_heatmap.png'")
    
    def plot_2023_close_price(self):
        """
        绘制2023年全年收盘价时序图
        """
        print("\n绘制2023年全年收盘价时序图...")
        # 确保日期列是datetime类型
        if '日期' in self.data.columns:
            self.data['日期'] = pd.to_datetime(self.data['日期'])
            # 筛选2023年的数据
            data_2023 = self.data[self.data['日期'].dt.year == 2023].copy()
            
            plt.figure(figsize=(12, 6))
            plt.plot(data_2023['日期'], data_2023['收盘'], marker='', linewidth=2, color='blue')
            plt.title('比亚迪2023年全年收盘价时序图')
            plt.xlabel('日期')
            plt.ylabel('收盘价')
            plt.grid(True, linestyle='--', alpha=0.7)
            
            # 设置x轴日期格式
            ax = plt.gca()
            ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
            ax.xaxis.set_major_locator(mdates.MonthLocator())
            plt.xticks(rotation=45)
            
            plt.tight_layout()
            plt.savefig('byd_2023_close_price.png', dpi=300)
            plt.close()
            print("2023年收盘价时序图已保存为 'byd_2023_close_price.png'")
        else:
            print("未找到日期列，请检查数据格式")
    
    def plot_k_line_chart(self):
        """
        绘制2023年4月到6月的K线图
        """
        print("\n绘制2023年4月到6月的K线图...")
        if '日期' in self.data.columns:
            # 筛选2023年4月到6月的数据
            data_2023_4_6 = self.data[
                (self.data['日期'].dt.year == 2023) & 
                (self.data['日期'].dt.month >= 4) & 
                (self.data['日期'].dt.month <= 6)
            ].copy()
            
            # 重命名列以适应mplfinance
            data_2023_4_6.rename(columns={
                '日期': 'Date',
                '开盘': 'Open',
                '最高': 'High',
                '最低': 'Low',
                '收盘': 'Close',
                '成交量': 'Volume'
            }, inplace=True)
            
            # 设置日期为索引
            data_2023_4_6.set_index('Date', inplace=True)
            
            # 绘制K线图
            mpf.plot(data_2023_4_6, 
                     type='candle', 
                     title='比亚迪2023年4月-6月K线图',
                     ylabel='价格',
                     volume=True,
                     ylabel_lower='成交量',
                     savefig='byd_k_line_chart.png',
                     figratio=(12, 6),
                     figscale=1.5)
            
            print("K线图已保存为 'byd_k_line_chart.png'")
            
            # K线图分析
            print("\nK线图分析:")
            print(f"分析期间: 2023年4月-6月，共{len(data_2023_4_6)}个交易日")
            print(f"起始价: {data_2023_4_6['Close'].iloc[0]:.2f}")
            print(f"结束价: {data_2023_4_6['Close'].iloc[-1]:.2f}")
            print(f"最高价: {data_2023_4_6['High'].max():.2f}")
            print(f"最低价: {data_2023_4_6['Low'].min():.2f}")
            
            price_change = data_2023_4_6['Close'].iloc[-1] - data_2023_4_6['Close'].iloc[0]
            price_change_pct = (price_change / data_2023_4_6['Close'].iloc[0]) * 100
            print(f"期间涨跌幅: {price_change:.2f} ({price_change_pct:.2f}%)")
        else:
            print("未找到日期列，请检查数据格式")
    
    def run_analysis(self):
        """
        运行完整分析流程
        """
        self.load_data()
        self.display_data_info()
        self.calculate_correlation()
        self.plot_2023_close_price()
        self.plot_k_line_chart()
        print("\n分析完成！")

if __name__ == "__main__":
    # 创建分析器实例并运行分析
    analyzer = BYDStockAnalyzer('比亚迪后复权历史行情数据.xlsx')
    analyzer.run_analysis()